package com.syf.core.service.run.chain.impl;

import com.syf.core.exception.ExceptionUtils;
import com.syf.core.service.context.ServiceContext;
import com.syf.core.service.enums.ResponseFormatEnums;
import com.syf.core.service.run.chain.ServicePrePostHandle;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ServicePrePostHandleChainNode {
    private ServicePrePostHandleChainNode pre;

    private ServicePrePostHandleChainNode next;

    private final ServicePrePostHandle handle;

    public ServicePrePostHandleChainNode(ServicePrePostHandle handle) {
        this.handle = handle;
    }

    void processPreHandle(ServiceContext context) {
        if (handle.support(context.getRequest().getHead().getServiceDefinition())) {
            try {
                boolean result = handle.preHandle(context);
                if (!result) { // 前处理要求中止，则中止执行链
                    log.debug("Pre-service processing end");
                    log.debug("Post-service processing begin");
                    processPostHandle(context);
                    return;
                }
            } catch (Throwable cause) {
                log.debug("Pre-service processing has exception");
                exceptionCaught(context, cause);
                return;
            }
        }

        if (next != null) {
            next.processPreHandle(context);
        }

    }

    void processPostHandle(ServiceContext context) {
        if (handle.support(context.getRequest().getHead().getServiceDefinition())) {
            try {
                handle.postHandle(context);
            } catch (Throwable cause) {
                log.debug("Post-service processing has exception");
                exceptionCaught(context, cause);
                return;
            }
        }

        if (pre != null) {
            pre.processPostHandle(context);
        }

    }

    /**
     * 异常处理
     */
    public void exceptionCaught(ServiceContext context, Throwable cause) {
        // 通用异常处理：打印日志，然后根据设置response
        log.error(ExceptionUtils.getExceptionStackInfo(cause));
        context.getResponse().setResp(ResponseFormatEnums.SERVICE_PROCESS_HAS_EXCEPTION);
    }

    public ServicePrePostHandleChainNode getPre() {
        return pre;
    }

    public void setPre(ServicePrePostHandleChainNode pre) {
        this.pre = pre;
    }

    public ServicePrePostHandleChainNode getNext() {
        return next;
    }

    public void setNext(ServicePrePostHandleChainNode next) {
        this.next = next;
    }
}
